package com.Limiter;

/**
 * @Package: com.Limiter
 * @ClassName: SlidingWindowRateLimiter
 * @Author: h2cloud
 * @CreateTime: 2024/3/16 9:41 下午
 * @Description:
 */

import lombok.extern.slf4j.Slf4j;

import java.util.LinkedList;

@Slf4j
public class SlidingWindowRateLimiter implements Limiter {
	private final long windowSize;  // 时间窗口大小（毫秒）
	private final int limit;        // 时间窗口内允许的请求数量
	private final LinkedList<Long> requestTimes;  // 存储请求时间戳的链表

	public SlidingWindowRateLimiter(long windowSize, int limit) {
		this.windowSize = windowSize;
		this.limit = limit;
		this.requestTimes = new LinkedList<>();
	}

	public synchronized boolean tryAcquire() {
		long currentTime = System.currentTimeMillis();

		// 清理过期的请求时间戳
		cleanupExpiredRequests(currentTime);

		// 如果当前请求数超过限制，拒绝该请求
		if (requestTimes.size() >= limit) {
			return false;
		}

		// 添加当前请求时间戳
		requestTimes.addLast(currentTime);
		return true;
	}

	private void cleanupExpiredRequests(long currentTime) {
		// 计算窗口开始时间
		long windowStartTime = currentTime - windowSize;

		// 只保留在时间窗口内的请求时间戳
		while (!requestTimes.isEmpty() && requestTimes.getFirst() <= windowStartTime) {
			requestTimes.removeFirst();
		}
	}

	public static void main(String[] args) throws InterruptedException {
		SlidingWindowRateLimiter limiter = new SlidingWindowRateLimiter(1000, 5);
		for (int i = 0; i < 100; i++) {
			log.info("Allow Request: " + limiter.tryAcquire());
			Thread.sleep(100); // 模拟请求间隔时间
		}
	}
}
